#ifndef __TINY_TEST__

#include "vbb_FLASHMEM.h"
#include "vbb_SAVE.h"
#include "vbb_FirmwareUtils.h"
#include "vbb_CARD.h"
#include "fw/vbb_RTC.h"
#include <stdarg.h>
#include <stdio.h>
#include <string.h>

VBB_Pin sdpin0;
VBB_Pin sdpin1;
VBB_Pin spapin_CS0;
VBB_Pin spapin_CS1;
//VBB_Pin spapin2;

VBB_Pin sdpin;

VBB_FlashMem flashMem;

//#define PAGE_END_OF_MSGMEM 65535
#define MSGQUEUE_NUM_OF_SECTOR  255
#define MSGQUEUE_NUM_OF_PAGE    65280
#define PAGE_PER_SECTOR         256
//#define PAGE_END_OF_MSGMEM 60000

void SPANSION_Band0_Select(void)
{
    if (vbb_DeviceModel() == CNS03)
        (GPIOE->BSRR |= (1 << (12 + 16)));    
    else if (vbb_DeviceModel() == CNS01 || vbb_DeviceModel() == BA01)
        (GPIOB->BSRR |= (1 << (0 + 16)));
}

void SPANSION_Band0_Deselect(void)
{
    if (vbb_DeviceModel() == CNS03)
        (GPIOE->BSRR |= (1 << (12 + 0)));    
    else if (vbb_DeviceModel() == CNS01 || vbb_DeviceModel() == BA01)
        (GPIOB->BSRR |= (1 << (0 + 0)));
}

void SPANSION_Band1_Select(void)
{
    if (vbb_DeviceModel() == CNS03)
        (GPIOE->BSRR |= (1 << (13 + 16)));    
    else if (vbb_DeviceModel() == CNS01 || vbb_DeviceModel() == BA01)
        (GPIOB->BSRR |= (1 << (1 + 16)));
}

void SPANSION_Band1_Deselect(void)
{
    if (vbb_DeviceModel() == CNS03)
        (GPIOE->BSRR |= (1 << (13 + 0)));    
    else if (vbb_DeviceModel() == CNS01 || vbb_DeviceModel() == BA01)
        (GPIOB->BSRR |= (1 << (1 + 0)));
}

extern void SD_Select(void);
extern void SD_Deselect(void);

void vbb_FLASHMEM_Init(void)
{         
    if (vbb_DeviceModel() == CNS03)
    {
        vbb_PIN_Init(&spapin_CS0, GPIOE, 12, PIN_MODE_GENERAL_OUTPUT_PUSH_PULL);    
        vbb_PIN_Init(&spapin_CS1, GPIOE, 13, PIN_MODE_GENERAL_OUTPUT_PUSH_PULL);            
        vbb_PIN_Init(&sdpin, GPIOC, 4, PIN_MODE_GENERAL_OUTPUT_PUSH_PULL);
    }
    else if (vbb_DeviceModel() == CNS01 || vbb_DeviceModel() == BA01)
    {
        vbb_PIN_Init(&spapin_CS0, GPIOB, 0, PIN_MODE_GENERAL_OUTPUT_PUSH_PULL);    
        vbb_PIN_Init(&spapin_CS1, GPIOB, 1, PIN_MODE_GENERAL_OUTPUT_PUSH_PULL);
        if (vbb_DeviceModel() == CNS01)
            vbb_PIN_Init(&sdpin, GPIOB, 7, PIN_MODE_GENERAL_OUTPUT_PUSH_PULL);
    }        
    
    if (vbb_DeviceModel() != BA01)
        SD_Deselect();
    SPANSION_Band0_Select();
    SPANSION_Band1_Select();
        
    vbb_DelayMillis(100);
    
    if (vbb_DeviceModel() != BA01)
        SD_Deselect();
    SPANSION_Band0_Deselect();    
    SPANSION_Band1_Deselect();

    if (vbb_DeviceModel() == CNS03)
        vbb_Flash_Init(&(flashMem.flash), 256, 65536, SPI3, GPIOE, 12);
    else if (vbb_DeviceModel() == CNS01 || vbb_DeviceModel() == BA01)
        vbb_Flash_Init(&(flashMem.flash), 256, 65536, SPI3, GPIOB, 0);
    
    /*
    vbb_OUTPUT_Print("INFO: SPANSION band 0 information: ");
    vbb_OUTPUT_PrintNumberUnSigned(vbb_Flash_ReadId(&(flashMem.flash)));
    vbb_OUTPUT_Print(" ");
    vbb_OUTPUT_PrintNumberUnSigned(vbb_Flash_ReadElectronicSignature(&(flashMem.flash)));
    vbb_OUTPUT_Print("\r\n");
    */
    
    vbb_CONSOLE_Printf("INFO: SPANSION die 0 information: %2xh %2xh.\r\n", vbb_Flash_ReadId(&(flashMem.flash)), vbb_Flash_ReadElectronicSignature(&(flashMem.flash)));

    flashMem.head = flashMem.tail = 0;   
    flashMem.sendhead = 0;   

    /*vbb_Flash_UnlockFlash(&(flashMem.flash));*/
    
    vbb_SAVE_LoadFlashInfo(&flashMem);
}

void vbb_FLASHMEM_PushMessageF(const char * Format, ...)
{
    va_list args;
	char * buf = flashMem.tmpmsg;        
    buf[0] = 0;    
    va_start(args, Format);	
    vsprintf(buf, Format, args);    

    vbb_FLASHMEM_PushMessage(buf);
}

extern VBB_RTC rtc;

char fullmsg[512];
char fileName[32];

unsigned int FLASHMEM_GetSectorSize(unsigned int Address)
{
    return 65536;
}

void vbb_FLASHMEM_PushMessage(const char * Message)
{    
    unsigned int curAddr;
    unsigned char checksum = 0;
    const char * tmp = Message;            
    
    curAddr = (flashMem.tail % MSGQUEUE_NUM_OF_PAGE) * flashMem.flash.pageSize;
    
    if ((flashMem.tail % PAGE_PER_SECTOR) == 0) // tail is on a new sector
    {
        // Cut off head for 1 sector
        if ((flashMem.head % MSGQUEUE_NUM_OF_PAGE) == (flashMem.tail % MSGQUEUE_NUM_OF_PAGE))
        {
            if (flashMem.tail > 0)
                flashMem.head += PAGE_PER_SECTOR; // skip 256 head messages
        }
        
        // and erase that free sector             
        vbb_Flash_EraseSector(&(flashMem.flash), curAddr);
    }
    
    checksum = 0;
    while (tmp[0] != 0)
    {        
        checksum ^= tmp[0];
        tmp++;
    }    
    
    // Clear all extra \r\n
    vbb_StrCpy(fullmsg, Message, vbb_GetLen(Message));
    vbb_CleanMessage(fullmsg, "\r\n");
    sprintf(fullmsg + vbb_GetLen(fullmsg), "*%02X\r\n", checksum);            
    
    vbb_Flash_EnableWrite(&(flashMem.flash));        
    
    vbb_StrCpy(flashMem.flash.tmpPage, fullmsg, vbb_GetLen(fullmsg));
    
    vbb_Flash_PageProgram(&(flashMem.flash), curAddr);    
    flashMem.tail++;
    
    vbb_SAVE_SaveFlashInfo(&flashMem);        
    
    sprintf(fileName, "%02d%02d%02d.%03d", rtc.year % 100, rtc.month, rtc.day, VERSION);
    vbb_CARD_PushMessage(fileName, fullmsg);
}

char * vbb_FLASHMEM_GetMessage(unsigned int Index)
{
    vbb_Flash_PageRead(&(flashMem.flash), (Index % MSGQUEUE_NUM_OF_PAGE) * flashMem.flash.pageSize);
    vbb_StrCpy(flashMem.tmpmsg, flashMem.flash.tmpPage, vbb_GetLen(flashMem.flash.tmpPage));
    return flashMem.tmpmsg;
}

void vbb_FLASHMEM_Clear(void)
{
    flashMem.head = flashMem.sendhead = flashMem.tail = 0;
    vbb_SAVE_SaveFlashInfo(&flashMem);
}

#endif
